package hdd.config;

import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
import org.springframework.cache.support.CompositeCacheManager;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.JedisPoolConfig;

import java.util.LinkedList;

@Configuration
@EnableCaching//启用缓存支持
@PropertySource( {"classpath:setting.properties"} )
public class CacheConfig implements EnvironmentAware {
    private  Environment environment ;

    //==============缓存 ===============
    @Bean
    public RedisCacheManager redisCacheManager(RedisTemplate redisTemplate){
        RedisCacheManager redisCacheManager = new RedisCacheManager( redisTemplate );
        redisCacheManager.setDefaultExpiration( environment.getProperty( "redis.expiration",Long.class ) );//缓存默认有效时长
        return redisCacheManager;
    }

    //连接池
    @Bean
    public JedisPoolConfig jedisPoolConfig(){
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig(  );
        jedisPoolConfig.setMaxIdle( environment.getProperty( "redis.maxIdle" ,Integer.class) );
        jedisPoolConfig.setMaxTotal( environment.getProperty( "redis.maxActive",Integer.class ) );
        jedisPoolConfig.setMaxWaitMillis( environment.getProperty( "redis.maxWait" ,Integer.class) );
        jedisPoolConfig.setTestOnBorrow(environment.getProperty( "redis.testOnBorrow",Boolean.class )  );
        return jedisPoolConfig;
    }

    @Bean
    public JedisConnectionFactory jedisConnectionFactory(JedisPoolConfig jedisPoolConfig){
        JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(  );
        jedisConnectionFactory.setPoolConfig( jedisPoolConfig );
        jedisConnectionFactory.setHostName( environment.getProperty( "redis.host" ) );
        jedisConnectionFactory.setPort(  environment.getProperty( "redis.port" ,Integer.class));
        String password = environment.getProperty( "redis.password" );
        if (password != null && !"".equals( password ) ){
            jedisConnectionFactory.setPassword( password );
        }
        jedisConnectionFactory.setDatabase( environment.getProperty( "redis.dbIndex" ,Integer.class) );
        return jedisConnectionFactory;
    }

    @Bean
    public RedisTemplate<String ,Object> redisTemplate (RedisConnectionFactory redisConnectionFactory){
        RedisTemplate<String ,Object>  redisTemplate = new RedisTemplate<String ,Object> ();
        redisTemplate.setConnectionFactory( redisConnectionFactory );
        redisTemplate.setKeySerializer( new StringRedisSerializer(  ) );
        redisTemplate.setValueSerializer( new JdkSerializationRedisSerializer() );
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

    // 一个基于内存的缓存，会随应用启用/关闭
    @Bean
    public ConcurrentMapCacheManager concurrentMapCacheManager(){
        return new  ConcurrentMapCacheManager();
    }

    @Primary
    @Bean("cacheManager")
    public CompositeCacheManager cacheManager(RedisCacheManager redisCacheManager, ConcurrentMapCacheManager concurrentMapCacheManager){
        CompositeCacheManager compositeCacheManager = new CompositeCacheManager(  );
        LinkedList<CacheManager> cacheManagers = new LinkedList<>(  );
        cacheManagers.add( redisCacheManager );
        cacheManagers.add( concurrentMapCacheManager );
        compositeCacheManager.setCacheManagers( cacheManagers );
        return compositeCacheManager;
    }

    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }
}
